#include "reduce.h"

#define RANGE 8
#define SIZE 80000

pthread_mutex_t lock;
pthread_barrier_t barrier;

class Tally {
public:
  int* count;
  const Tally operator+(const Tally &other) const;
  const Tally operator=(const Tally &rhs);
  Tally() {};
  Tally(Tally const& t) {
    count = new int[RANGE];
    for(INDEX i=0; i<RANGE; i++)
      count[i]=t.count[i];
  }
  ~Tally();
};

const Tally Tally::operator+(const Tally &other) const {
  Tally result;
  result.count = new int[RANGE];
  for(INDEX i=0; i<RANGE; i++)
    result.count[i] = this->count[i]+other.count[i];
  return result;
}

const Tally Tally::operator=(const Tally &rhs) {
  for(INDEX i=0; i<RANGE; i++) {
    this->count[i] = rhs.count[i];
  }
  return *this;
}

Tally::~Tally() {
  delete [] count;
}

class Prefix: public Reducer<int, Tally>
{
public:
  void init(Tally& t) {
    t.count = new int[RANGE];
    for(INDEX i=0; i<RANGE; i++)
      t.count[i] = 0;
  }
  void accum(Tally& t, int d) {t.count[d]++;}
  void combine(Tally& left, Tally right) { left=left+right;}
  Tally reduce(Tally t) { return t;}
  Prefix(int* data, INDEX length)
    : Reducer<int, Tally>(data, length) {}
};

int main() {
  int* a = (int*) new int [SIZE];
  for(int i=0; i<SIZE; i++) 
    a[i] = rand()%RANGE;

  Prefix prefix(a, SIZE);
  prefix.Start();

 // Tally b = prefix.result;
 // for(int i=0; i<RANGE; i++)
 //   cout<<b.count[i]<<endl;
  pthread_exit(NULL);
}
